package Client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import DBUtil.CNN;
import GroupWare.Pip;
import InetAgreement.InetDataEncapsulation;
import Tools.Log;
import XML.XML;
import XML.XMLNode;

/**
 * C-S客户端线程类 数据处理:ClientListener监听器 会话语言:XML
 * 
 * @author Administrator
 * 
 */
public class ClientThread implements Runnable {
	protected Socket s;
	private Vector<ClientListener> alcl = new Vector<ClientListener>();// 注册的监听器
	private InetDataEncapsulation dp = new InetDataEncapsulation();// 数据封包对象
	private volatile BufferedReader in;// 接收流
	private volatile PrintWriter out;// 发送流
	protected Thread thread;
	private final Pip p;// 服务器地址信息
	private StringBuffer data = new StringBuffer();// 数据缓冲
	private ExecutorService exeService = Executors.newCachedThreadPool();

	/**
	 * 构造客户端与服务器通信的对象
	 * 
	 * @param address
	 * @param port
	 * @throws IOException
	 * @throws UnknownHostException
	 */
	public ClientThread(String address, int port) throws UnknownHostException {
		InetAddress ia = InetAddress.getByName(address);
		p = new Pip(ia, port);
	}

	/**
	 * 服务器返回指令处理函数
	 * 
	 * @param cmd
	 *            单个指令包
	 */
	public void actCmd(final XML cmd) {
		Vector<XMLNode> al = new Vector<XMLNode>(0);
		cmd.getList(null, al, false);// 取主命令列表

		while (al.size() > 0) {
			XMLNode xn = al.remove(0);
			XML xml = cmd.remove(xn);
			xml.copy(xn);
			MsgEvent ce = new MsgEvent(this, xml);
			// ======触发监听器开始======
			for (int i = 0; i < alcl.size(); i++) {
				alcl.get(i).onMsgEvent(ce);
			}
			// ======触发监听器结束======

		}
	}

	public void addClientListenser(ClientListener cl) {
		alcl.add(cl);
	}

	/**
	 * 关闭对象
	 */
	public void Close() {
		try {
			if (out != null)
				out.close();
			if (in != null)
				in.close();

			if (s != null){
				s.close();
				s=null;
			}
			thread = null;
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 连接服务器
	 */
	public boolean Connect() {
		try {
			// 连接成功，创建网络流
			s = new Socket();
			s.connect(new InetSocketAddress(p.getAddress(), p.getPort()), 3000);
			
			ConnectAfterImpl();
			// //////////////////////////////////////////
			return true;
		} catch (Exception e) {
			Log.print(e);
		}
		return false;
	}

	protected void ConnectAfterImpl() throws IOException {
		ConnectAfterInitStream();
		// ///////////初始化数据监听线程///////////////
		if (thread != null && thread.isAlive()) {
			thread.stop();
		}
		thread = new Thread(this);
		thread.start();// 启动数据包接收线程

		Log.print("[Connect]" + p);
		
		String name = CNN.getConfig().GetPathValue("User:id").toString();
		String pass = CNN.getConfig().GetPathValue("User:pwd").toString();
		login(name, pass);// 匿名登录服务器

	}

	protected void ConnectAfterInitStream() throws IOException {
		in = new BufferedReader(new InputStreamReader(s.getInputStream()));
		out = new PrintWriter(s.getOutputStream(), true);

	}

	public void DispalyListener() {
		for (int i = 0; i < alcl.size(); i++) {
			System.out.println(i + alcl.get(i).toString());
		}
	}

	public InetAddress getInetAddress() {
		return s.getInetAddress();
	}

	public InetAddress getLocalAddress() {
		return s.getLocalAddress();
	}

	public Pip getPip() {
		return p;
	}

	/**
	 * 通知监听器，触发事件
	 * 
	 * @param ce
	 */
	protected void InformListener(ClientEvent ce) {

//		for (i.put(0, 0); i.get(0) < alcl.size(); i.put(0, i.get(0) + 1)) {
//			alcl.get(i.get(0)).ServRev(ce);
//		}
	}

	public boolean isConnected() {
		return s != null && !s.isClosed() && s.isConnected();
	}

	protected boolean login(String name, String pass) {
		return true;
	}

	public void removeClientListenser(ClientListener cl) {
		alcl.remove(cl);
	}

	/**
	 * 接收数据包线程
	 */
	@Override
	public void run() {
		for (;isConnected()&&thread == Thread.currentThread();)
		{
			runReadNetBytes();
		}
	}

	protected void runReadNetBytes() {
		String str = null;
		try {
			// //////////// 解析数据包 /////////////
			while ((str = in.readLine()) != null) {
				data.append(str);
				Log.print("RecvLine: " + str);
				while ((str = dp.baleBreaking(data)) != null) {
					final String xmlStr = str;
					Log.print("RecvPack: " + (str.length()<1024?str:str.substring(0, str.indexOf(">",1))));
					exeService.execute(new Runnable() {
						@Override
						public void run() {
							actCmd(new XML(xmlStr));
						}
					});
				}
			}// ////////////////// /////////////
			Thread.sleep(100);
		} catch (Exception e) {
			e.printStackTrace();
			Log.print("[Incept]C<S Exception:" + e.getMessage());
			Close();// 异常关闭自己
			// /////////////////触发客户断开连接事件//////////////////////
			CloseEvent ce = new CloseEvent(this);
			for (int i = 0; i < alcl.size(); i++) {
				alcl.get(i).onCloseEvent(ce);
			}// //////////////////////////////////////////////
			Log.print("[ClientClose]C-S:连接中断!");
		} finally {

		}
	}

	/**
	 * 向服务器发送请求
	 * 
	 * @param data
	 */
	public synchronized void send(Object data) {
		if (isConnected()) {
			String str = dp.Package(data.toString());
			out.println(str);// 数据封包发送
			out.flush();// 刷新缓冲区把数据写往客户端
			if (str.indexOf("pulse") == -1) {
				Log.print("[Client]Send  >>  " + (str.length()<1024?str:str.substring(0, str.indexOf(">",1))));
//				Thread.dumpStack();
			}
		}
	}

	public void send(XML data) {
		send(data.toString());
	}

	public void send(XMLNode data) {
		send(data.toString());
	}

	public void sendMessage(Object cmd) {
		send(cmd);
	}

	public void setAddress(String address, int sport) {
		try {
			InetAddress ia = InetAddress.getByName(address);
			p.setAddress(ia);
			p.setPort(sport);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
			
	}

	public void send(byte[] buf, int offset, int len) {
	}
}
